package com.jiangds.open.check;

import com.jiangds.open.exception.CheckException;
import com.jiangds.open.exception.CheckExceptionFactory;

/**
 * {@link Checker}  校验器,定义一些极为常用的校验方法
 *
 * @author jiangliang
 * @since 2021/1/5 13:45
 */

public interface Checker<R extends Number,T>{

    /**
     * 是否校验通过
     * @return  true 通过
     *          false 不通过
     */
    boolean isPass();

    /**
     * 对象 != null
     * 字符串 !=null 并且 != ""
     * 集合 !=null 并且 size > 0
     * @return 校验器自身
     */
    Checker<R,T> notEmpty();

    /**
     * 数字 两个值之间
     * 字符串 长度范围
     * 集合 size范围
     * 日期 往前min天之内, 往后max天之内 例子:
     *     当前时间是 2020-01-01 min = 1 ,max = 1;
     *     则日期范围必须是 2019-12-31 至 2020-01-02之间,可以使用负数
     * @param min 范围开始
     * @param max 范围结束
     * @return 校验器自身
     */
    Checker<R,T> range(R min, R max);

    /**
     * 大于某个值
     * @param greaterThan 比较值
     * @return
     */
    Checker<R,T> greater(T greaterThan);

    /**
     * 小于某个值
     * @param lessThan 比较值
     * @return
     */
    Checker<R,T> less(T lessThan);

    /**
     * 在众多值之中即可
     * @param args 众多值
     * @return
     */
    @SuppressWarnings({"unchecked", "varargs"})
    Checker<R,T> in(T ... args);

    /**
     * 正则匹配,仅仅支持数字和字符串
     * 其他的全部返回true
     * @param regex 正则表达式
     * @return
     */
    Checker<R,T> regex(String regex);

    /**
     * 最终校验,如果不通过的情况下 抛出异常信息{@link CheckException}
     * @param msg 异常信息
     * @return 成功
     */
    default boolean check(String msg){
        if(!isPass()){
            throw CheckExceptionFactory.build(msg);
        }
        return true;
    }

    /**
     * 多校验器校验,如果不通过的情况下 抛出异常信息{@link CheckException}
     * @param checker 下一个校验器
     * @param thisMsg 当前校验器不通过的时候抛出的异常消息
     * @param msg 下一个校验器不通过的时候抛出的异常消息
     * @return 成功
     */
    default boolean and(Checker<R,T> checker, String thisMsg, String msg){
        return this.check(thisMsg) && checker.check(msg);
    }
}
